{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "86612141",
   "metadata": {},
   "outputs": [],
   "source": [
    "# This is a sample Python script.\n",
    "import os\n",
    "import re\n",
    "from datetime import timedelta\n",
    "import pandas as pd\n",
    "\n",
    "HOUR = 60 * 60 * 1000\n",
    "MINUTE = 60 * 1000\n",
    "\n",
    "# 找rtc最相关的wakeup alarm\n",
    "#\n",
    "file_id = 1\n",
    "all_attri_num = pd.DataFrame()\n",
    "\n",
    "# 不同策略下的数据\n",
    "# 不同策略下的数据\n",
    "networks = [\"wifi\"]\n",
    "strategies_list = [\"fullAlign\",\"origin\"]\n",
    "network_data = {\"wifi\":{}}\n",
    "for n in networks:\n",
    "    tmp = {}\n",
    "    for s in strategies_list:\n",
    "        tmp[s] = {\"rtc_alarm\": [], \"drain\": []}\n",
    "    network_data[n] = tmp\n",
    "\n",
    "stratgies = {\n",
    "    \"fullAlign\": {\"rtc_alarm\": [], \"drain\": []},\n",
    "    \"origin\": {\"rtc_alarm\": [], \"drain\": []}\n",
    "}\n",
    "\n",
    "# 将时间字符串转换为毫秒\n",
    "def parse_time(time_str):\n",
    "    h_match = re.search(r'(?P<hour>\\d+)h\\d+', time_str)\n",
    "    m_match = re.search(r'(?P<minute>\\d+)m\\d+', time_str)\n",
    "    s_match = re.search(r'(?P<second>\\d+)s\\d+', time_str)\n",
    "    ms_match = re.search(r'(?P<millisecond>\\d+)ms', time_str)\n",
    "\n",
    "    h = int(h_match.group('hour')) if h_match else 0\n",
    "    m = int(m_match.group('minute')) if m_match else 0\n",
    "    s = int(s_match.group('second')) if s_match else 0\n",
    "    ms = int(ms_match.group('millisecond')) if ms_match else 0\n",
    "\n",
    "    total_ms = h * 60 * 60 * 1000 + m * 60 * 1000 + s * 1000 + ms\n",
    "    if total_ms == 0:\n",
    "        return None\n",
    "    else:\n",
    "        return total_ms\n",
    "\n",
    "def get_time(time_str):\n",
    "    h_match = re.search(r'(?P<hour>\\d+)h\\d+', time_str)\n",
    "    m_match = re.search(r'(?P<minute>\\d+)m\\d+', time_str)\n",
    "    s_match = re.search(r'(?P<second>\\d+)s\\d+', time_str)\n",
    "    ms_match = re.search(r'(?P<millisecond>\\d+)ms', time_str)\n",
    "\n",
    "    h = int(h_match.group('hour')) if h_match else 0\n",
    "    m = int(m_match.group('minute')) if m_match else 0\n",
    "    s = int(s_match.group('second')) if s_match else 0\n",
    "    ms = int(ms_match.group('millisecond')) if ms_match else 0\n",
    "\n",
    "\n",
    "    return timedelta(hours=int(h),minutes=int(m), seconds=int(s), milliseconds=int(ms))\n",
    "\n",
    "# 处理每一行数据\n",
    "def process_drain_line(line):\n",
    "    screen_off_time = None\n",
    "    screen_on_time = None\n",
    "    charge_on_screen = None\n",
    "\n",
    "    time = parse_time(line.split()[1])\n",
    "\n",
    "    charge_search = re.search(r'charge=(\\d+)', line)\n",
    "    if charge_search:\n",
    "        charge = int(charge_search.group(1))\n",
    "\n",
    "    if \"-screen\" in line and screen_off_time is None:\n",
    "        screen_off_time = time\n",
    "\n",
    "    if \"+screen\" in line:\n",
    "        screen_on_time = time\n",
    "        charge_on_screen = charge\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "def parse_log_line(line):\n",
    "    line = line.lstrip()\n",
    "    match = re.search(r\"(\\d+ms).*?(wake_reason=0:\\\"\\d+ qpnp_rtc_alarm\\\"|\\\"\\*walarm\\*:|\\\"\\*alarm\\*:).*\",\n",
    "                      line)\n",
    "    if match:\n",
    "        return (get_time(line), match.group(2))\n",
    "\n",
    "    return None\n",
    "\n",
    "def parse_log(path):\n",
    "    f = open(path, encoding=\"utf-8\")\n",
    "    fileContent = f.readlines()\n",
    "    f.close()\n",
    "    return fileContent\n",
    "\n",
    "def parse_timestamp(timestamp_str):\n",
    "    m, s, ms = re.match(r\"\\+(\\d+)m(\\d+)s(\\d+)ms\", timestamp_str).groups()\n",
    "    return timedelta(minutes=int(m), seconds=int(s), milliseconds=int(ms))\n",
    "\n",
    "def is_less_than_half_second(t1, t2):\n",
    "    return abs(t1 - t2) < timedelta(seconds=0.5)\n",
    "\n",
    "def count_alarm_walarm(line):\n",
    "    alarm = 0\n",
    "    walarm = 0\n",
    "    line = line.lstrip()\n",
    "    if re.search(r':\"\\*walarm\\*:',line):\n",
    "        walarm = 1\n",
    "    if re.search(r':\"\\*alarm\\*:',line):\n",
    "        alarm = 1\n",
    "    return walarm,alarm\n",
    "\n",
    "def get_rtc_alarm_num(line):\n",
    "    match = re.search(r'.*qpnp_rtc_alarm:.*(\\d+)\\s*times', line)\n",
    "    if match:\n",
    "        qpnp_rtc_alarm = int(match.group(1))\n",
    "    return qpnp_rtc_alarm\n",
    "\n",
    "\n",
    "def count_event(content):\n",
    "    batteryContentFlag = False\n",
    "    batteryContentOutFlag = False\n",
    "\n",
    "    wakeupContentFlag = False\n",
    "    wakeupContentOutFlag = False\n",
    "    # qpnp_rtc_alarm出现wakelock为walarm或者alarm次数\n",
    "    walarm_rtc_count = 0\n",
    "    alarm_rtc_count = 0\n",
    "\n",
    "    # wakelock为walarm或者alarm次数\n",
    "    w_count = 0\n",
    "    a_count = 0\n",
    "\n",
    "    atc_drain = 0\n",
    "    duration = \"0\"\n",
    "    qpnp_rtc_alarm = 0\n",
    "    app_wakeup_alarm_num = 0\n",
    "\n",
    "    prev_timestamp = None\n",
    "\n",
    "    # 计算真实耗电相关变量\n",
    "    time = None\n",
    "    screen_off_time = None\n",
    "    screen_on_time = None\n",
    "    charge_start = None\n",
    "    charge_end = None\n",
    "    charge_time = None\n",
    "    charge_start_flag = False\n",
    "\n",
    "    # time pattern\n",
    "\n",
    "    app_wakeup_num = 0\n",
    "    app_wakeup = pd.DataFrame()\n",
    "\n",
    "    for line in content:\n",
    "        # Judge arrive batterystats paragraph\n",
    "        line = line.lstrip()\n",
    "        if not batteryContentFlag:\n",
    "            if re.search(r\"DUMP OF SERVICE batterystats:.*\", line):\n",
    "                batteryContentFlag = True\n",
    "\n",
    "        # Judge out batterystats paragraph\n",
    "        if (batteryContentOutFlag is False) and (batteryContentFlag is True):\n",
    "            if re.search(r\"Per-PID Stats:.*\", line):\n",
    "                batteryContentOutFlag = True\n",
    "                batteryContentFlag = False\n",
    "\n",
    "        # Judge arrive app status\n",
    "        if (batteryContentOutFlag is True) and (wakeupContentFlag is False):\n",
    "            if re.search(\"Resource Power Manager Stats\", line):\n",
    "                wakeupContentFlag = True\n",
    "\n",
    "        # Judge out app status\n",
    "        if (wakeupContentOutFlag is False) and (wakeupContentFlag is True):\n",
    "            if re.search(\"Total cpu time reads: \", line):\n",
    "                wakeupContentFlag = False\n",
    "                wakeupContentOutFlag = True\n",
    "\n",
    "\n",
    "\n",
    "        if batteryContentFlag:\n",
    "            if line.split():\n",
    "                tmp = parse_time(line.split()[0])\n",
    "                if tmp is not None:\n",
    "                    time = tmp\n",
    "\n",
    "            # 计算真实耗电量\n",
    "            charge_search = re.search(r'charge=(\\d+)', line)\n",
    "            if charge_search:\n",
    "                charge = int(charge_search.group(1))\n",
    "                charge_time = time\n",
    "                if charge_time is not None and charge_time > 22 *  HOUR + 59 * MINUTE:\n",
    "                    screen_on_time = charge_time\n",
    "                    charge_end = charge\n",
    "                    batteryContentFlag = False\n",
    "                    batteryContentOutFlag = True\n",
    "\n",
    "            # 当灭屏后，flag标志位置为true，记录第一个charge\n",
    "            if charge_start_flag:\n",
    "                charge_start_flag = False\n",
    "                charge_start = charge\n",
    "\n",
    "            if \"-screen\" in line and screen_off_time is None:\n",
    "                screen_off_time = time\n",
    "                charge_start_flag = True\n",
    "\n",
    "\n",
    "\n",
    "            # 统计qpnp_rtc_alarm\n",
    "            parsed_line = parse_log_line(line)\n",
    "\n",
    "\n",
    "            m,n=count_alarm_walarm(line)\n",
    "            w_count += m\n",
    "            a_count += n\n",
    "            if parsed_line is None:\n",
    "                # 匹配qpnp_rtc_alarm\n",
    "                rtc_match = re.search(r'qpnp_rtc_alarm:.*\\((\\d+) times\\)', line)\n",
    "                if rtc_match:\n",
    "                    qpnp_rtc_alarm = int(rtc_match.group(1))\n",
    "\n",
    "\n",
    "                # 匹配actual drain\n",
    "                # Match the actual drain numbers and calculate the average\n",
    "                drain_match = re.search(r'actual drain: (\\d+\\.?\\d*)-(\\d+\\.?\\d*)', line)\n",
    "                if drain_match:\n",
    "                    num1 = float(drain_match.group(1))\n",
    "                    num2 = float(drain_match.group(2))\n",
    "                    atc_drain = (num1 + num2) / 2\n",
    "\n",
    "                # Match the durations\n",
    "                duration_matches = re.search(r'idle:.*duration: ([\\dhms\\. ]+)', line)\n",
    "                if duration_matches:\n",
    "                    duration = duration_matches.group(1)\n",
    "                continue\n",
    "\n",
    "\n",
    "            timestamp, event = parsed_line\n",
    "\n",
    "            if 'wake_reason=0:\"546 qpnp_rtc_alarm\"' in event:\n",
    "                qpnp_rtc_alarm +=1;\n",
    "                prev_timestamp = timestamp\n",
    "            elif prev_timestamp is not None and '*walarm*:' in event and abs(prev_timestamp - timestamp) < timedelta(\n",
    "                    seconds=0.5):\n",
    "                walarm_rtc_count += 1\n",
    "                prev_timestamp = None\n",
    "            elif prev_timestamp is not None and '*alarm*:' in event and abs(prev_timestamp - timestamp) < timedelta(\n",
    "                    seconds=0.5):\n",
    "                alarm_rtc_count += 1\n",
    "                prev_timestamp = None\n",
    "\n",
    "        if wakeupContentFlag:\n",
    "            # 统计App wakeup alarm\n",
    "            # if \"Wakeup alarm *walarm*:\" in line:\n",
    "\n",
    "            # 根据apk名称统计\n",
    "            app_name_pattern = re.search(r'Apk\\s(.+?):',line)\n",
    "            if app_name_pattern:\n",
    "                if app_wakeup_num != 0:\n",
    "                    app_wakeup[app_name] = attri_num\n",
    "                app_wakeup_num = 0\n",
    "                app_name = app_name_pattern.group(1)\n",
    "            s_app_wakeup = re.search(r'Wakeup alarm \\*walarm\\*:(.+?):\\s(\\d+)\\s+times', line)\n",
    "            if s_app_wakeup:\n",
    "                attri = s_app_wakeup.group((1))\n",
    "                attri_num = int(s_app_wakeup.group((2)))\n",
    "                app_wakeup_alarm_num += attri_num\n",
    "                app_wakeup_num += attri_num\n",
    "        if wakeupContentOutFlag :\n",
    "            if app_wakeup_num != 0:\n",
    "                app_wakeup[app_name] = attri_num\n",
    "            break\n",
    "\n",
    "\n",
    "            # TODO:统计不同应用的waekup alarm，找到与qpnp_rtc_alarm关系最大的那个\n",
    "\n",
    "    print(\"App wakeup alarm：\"+str(app_wakeup_alarm_num))\n",
    "\n",
    "    \n",
    "\n",
    "    # 将文件中的wakeup数量增加到全局变量中\n",
    "    global all_attri_num\n",
    "    all_attri_num = pd.concat([all_attri_num, app_wakeup], axis=0, ignore_index=True)\n",
    "\n",
    "    if charge_end == None:\n",
    "        charge_end = charge\n",
    "    if screen_on_time == None:\n",
    "        screen_on_time = charge_time\n",
    "    if screen_off_time is None:\n",
    "        total_hour = screen_on_time / (60 * 60 * 1000)\n",
    "    else:\n",
    "        total_hour = (screen_on_time - screen_off_time) / (60 * 60 * 1000)\n",
    "    total_drain = charge_start - charge_end\n",
    "    \n",
    "    # 增加属性\n",
    "    app_wakeup[\"wakeup_alarm\"] = app_wakeup_alarm_num\n",
    "    app_wakeup[\"qpnp_rtc_alarm\"] = qpnp_rtc_alarm / total_hour\n",
    "    \n",
    "    avg_drain = total_drain / total_hour\n",
    "    return walarm_rtc_count + alarm_rtc_count, w_count + a_count,qpnp_rtc_alarm,atc_drain,duration,avg_drain,total_hour\n",
    "\n",
    "def print_hi(name):\n",
    "    # Use a breakpoint in the code line below to debug your script.\n",
    "    print(f'Hi, {name}')  # Press Ctrl+F8 to toggle the breakpoint.\n",
    "\n",
    "def count_Walarm_Qpnp(path):\n",
    "    fileContent = parse_log(path)\n",
    "    walarm_alarm_rtc_count,w_a_count,rtc_count,actual_drain,duration,avg_drain,test_time = count_event(fileContent)\n",
    "    print(\"test duration:\" + duration)\n",
    "    print(\"test time:\" + str(test_time)+\"h\")\n",
    "    # print(\"qpnp_rtc_alarm:\" + str(rtc_count))\n",
    "    # print(\"actual drain:\" + f\"{actual_drain:.2f}\")\n",
    "    print(\"walarm&rtc_alarm Count+alarm&rtc_alarm Count:\" + str(walarm_alarm_rtc_count) )\n",
    "    print(\"alarm Count + walarm Count:\" + str(w_a_count))\n",
    "    print(\"average drain:\" + f\"{avg_drain:.2f}\"+\"\\n\")\n",
    "    \n",
    "    if test_time < 3.9:\n",
    "        return None,None\n",
    "    return walarm_alarm_rtc_count, avg_drain\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "776c09a6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "fullAlign\n",
      "device1_0921_1.txt: \n",
      "App wakeup alarm：468\n",
      "test duration:0\n",
      "test time:18.23928666666667h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:240\n",
      "alarm Count + walarm Count:310\n",
      "average drain:20.23\n",
      "\n",
      "device1_0925_1.txt: \n",
      "App wakeup alarm：1597\n",
      "test duration:0\n",
      "test time:22.99968h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:351\n",
      "alarm Count + walarm Count:471\n",
      "average drain:18.74\n",
      "\n",
      "device4_0922_1.txt: \n",
      "App wakeup alarm：426\n",
      "test duration:0\n",
      "test time:14.055784166666667h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:226\n",
      "alarm Count + walarm Count:293\n",
      "average drain:24.83\n",
      "\n",
      "device4_align_0927_1.txt: \n",
      "App wakeup alarm：380\n",
      "test duration:0\n",
      "test time:15.726667222222222h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:203\n",
      "alarm Count + walarm Count:296\n",
      "average drain:21.36\n",
      "\n",
      "device4_align_0926_1.txt: \n",
      "App wakeup alarm：228\n",
      "test duration:0\n",
      "test time:7.89865h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:134\n",
      "alarm Count + walarm Count:191\n",
      "average drain:19.12\n",
      "\n",
      "device4_0921_2.txt: \n",
      "App wakeup alarm：169\n",
      "test duration:0\n",
      "test time:5.163515h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:77\n",
      "alarm Count + walarm Count:123\n",
      "average drain:26.53\n",
      "\n",
      "device1_align_0926_1.txt: \n",
      "App wakeup alarm：203\n",
      "test duration:0\n",
      "test time:7.903823888888889h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:68\n",
      "alarm Count + walarm Count:146\n",
      "average drain:20.88\n",
      "\n",
      "device1_align_0927_1.txt: \n",
      "App wakeup alarm：391\n",
      "test duration:0\n",
      "test time:15.712601944444444h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:257\n",
      "alarm Count + walarm Count:317\n",
      "average drain:19.86\n",
      "\n",
      "origin\n",
      "device1_origin_0926_1.txt: \n",
      "App wakeup alarm：391\n",
      "test duration:0\n",
      "test time:13.306797777777778h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:228\n",
      "alarm Count + walarm Count:302\n",
      "average drain:10.15\n",
      "\n",
      "device4_0925_1.txt: \n",
      "App wakeup alarm：1598\n",
      "test duration:0\n",
      "test time:22.99893h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:355\n",
      "alarm Count + walarm Count:484\n",
      "average drain:20.00\n",
      "\n",
      "device1_0921_2.txt: \n",
      "App wakeup alarm：262\n",
      "test duration:0\n",
      "test time:5.151598333333333h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:119\n",
      "alarm Count + walarm Count:178\n",
      "average drain:32.42\n",
      "\n",
      "device4_0921_1.txt: \n",
      "App wakeup alarm：498\n",
      "test duration:0\n",
      "test time:18.23848111111111h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:276\n",
      "alarm Count + walarm Count:374\n",
      "average drain:22.15\n",
      "\n",
      "device1_0922_1.txt: \n",
      "App wakeup alarm：436\n",
      "test duration:0\n",
      "test time:14.058845h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:246\n",
      "alarm Count + walarm Count:340\n",
      "average drain:22.62\n",
      "\n",
      "device4_origin_0925_2.txt: \n",
      "App wakeup alarm：261\n",
      "test duration:0\n",
      "test time:8.115886388888889h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:122\n",
      "alarm Count + walarm Count:211\n",
      "average drain:19.96\n",
      "\n",
      "device1_origin_0925_2.txt: \n",
      "App wakeup alarm：277\n",
      "test duration:0\n",
      "test time:8.128565h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:92\n",
      "alarm Count + walarm Count:196\n",
      "average drain:19.19\n",
      "\n",
      "device4_origin_0926_1.txt: \n",
      "App wakeup alarm：383\n",
      "test duration:0\n",
      "test time:13.292999444444444h\n",
      "walarm&rtc_alarm Count+alarm&rtc_alarm Count:221\n",
      "alarm Count + walarm Count:294\n",
      "average drain:25.35\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 可选参数flight 、 wifi 、lte\n",
    "for network_pattern in networks:\n",
    "    # fullAlign对应完整的预测模块，align对应部分预测模块，paper对应对比论文，origin对应原生\n",
    "    data_path = \"../batteryStats/oppo/v0.3/pixel\"\n",
    "\n",
    "    # 将batterystats的txt文件放入下列路径中\n",
    "    fullAlign_path = os.path.join(data_path, network_pattern, strategies_list[0])\n",
    "    origin_path = os.path.join(data_path, network_pattern, strategies_list[1])\n",
    "    # align_path = \"batteryStats/align\"\n",
    "    # origin_path = \"batteryStats/origin\"\n",
    "\n",
    "    strtegies_path = [fullAlign_path,origin_path]\n",
    "\n",
    "\n",
    "\n",
    "    for i in range(len(strategies_list)):\n",
    "        print(strategies_list[i])\n",
    "        for file_name in os.listdir(strtegies_path[i]):\n",
    "            print(file_name + \": \")\n",
    "            rtc_alarm,drain=count_Walarm_Qpnp(os.path.join(strtegies_path[i], file_name))\n",
    "            # 添加数据\n",
    "            if rtc_alarm == None or drain == None:\n",
    "                    continue\n",
    "            network_data.get(network_pattern).get(strategies_list[i]).get(\"rtc_alarm\").append(rtc_alarm)\n",
    "            network_data.get(network_pattern).get(strategies_list[i]).get(\"drain\").append(drain)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "3f2cc714",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGzCAYAAAAFROyYAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA8k0lEQVR4nO3de1xVdb7/8fcGZQNyMbxwGTFMTGBETSpFxdRMRDIJnOmm4YzpxKCdNMsfjWNeSsqxk9WYnc7DtCatOTlKZzgleUPJ0Ekc84aOeiCdI+CMJiggCuzfH/Ng5w5UNoJ7bXg9H4/10LXWd639WW758t7r8t0mi8ViEQAAgIG4OLoAAACAHyOgAAAAwyGgAAAAwyGgAAAAwyGgAAAAwyGgAAAAwyGgAAAAwyGgAAAAwyGgAAAAwyGgtFLDhw/X8OHDbZaVlJRowoQJ6tSpk0wmk5YtW6bs7GyZTCZlZ2c7pM7mtHr1aplMJhUWFjq6FKBNu1X9z/z582UymW6+4B8JCQnR5MmTm32/sE87RxeAW2fmzJnKysrSSy+9pICAAN19990qLi6+6f1+/vnn+stf/qL58+fffJEAWqWW6n/QehFQWqkvv/yy3rKtW7dq/Pjxmj17tnXZnXfeqcrKSrm5uTX5tT7//HMtX76cgAJA0q3tf1rC0aNH5eLCBQZH4x1opdzc3Or90J85c0YdO3a0Webi4iJ3d/cm/TCWl5ffTImGV1FR4egSAKd0K/qfxqqtrdWlS5fs2sZsNqt9+/YtVBEai4BiYPv375fJZNJ///d/W5fl5eXJZDJpwIABNm3j4uI0cOBA6/zV14Dr7s2wWCxavny5TCaT9bptY68B113rPXz4sB5//HHddtttGjp0qCZPnqzly5dLknW/V18Trq2t1ZtvvqnIyEi5u7urS5cuGjNmjPbs2WPXv8PkyZN1xx13yN3dXQEBAfrlL3+ps2fP3nDbzz77TPHx8QoKCpLZbFbPnj21aNEi1dTU2LQbPny4+vTpo7y8PA0bNkyenp568cUXVVhYKJPJpKVLl2r58uW644475OnpqdGjR+vUqVOyWCxatGiRunXrJg8PD40fP17nzp1r9LEBRmWk/keSvvrqK91zzz1yd3dXz5499R//8R8NtjOZTJo+fbrWrFmjn/70pzKbzdq4caMkaenSpRo8eLA6deokDw8PRUVFad26dfX28eN7UOqOYefOnZo1a5a6dOmiDh066OGHH9Y//vGPG9aOpuESj4H16dNHHTt21I4dO/TQQw9JknJycuTi4qJvv/1WZWVl8vHxUW1trb7++mtNmzatwf0MGzZMf/jDHzRp0iQ98MADevLJJ5tc089+9jP16tVLixcvlsVi0V133aXTp09r06ZN+sMf/lCv/ZQpU7R69WrFxcXpqaeeUnV1tXJycrRr1y7dfffdjXrNTZs26X//93/1i1/8QgEBATp06JDee+89HTp0SLt27bruTXKrV6+Wl5eXZs2aJS8vL23dulXz5s1TWVmZfve739m0PXv2rOLi4vToo49q4sSJ8vf3t65bs2aNLl++rBkzZujcuXNasmSJfv7zn2vkyJHKzs7WnDlzdPz4cb399tuaPXu23n///Ub+iwLGZKT+58CBAxo9erS6dOmi+fPnq7q6Wi+99JLNz+jVtm7dqv/6r//S9OnT1blzZ4WEhEiS3nzzTT300EN64okndPnyZX3yySf62c9+pszMTMXHx9+wjhkzZui2227TSy+9pMLCQi1btkzTp0/XH//4R7uPCY1ggaHFx8db7r33Xut8YmKiJTEx0eLq6mr54osvLBaLxbJ3716LJMtnn31mbXffffdZ7rvvPpt9SbKkpqbaLNu2bZtFkmXbtm3XreOll16ySLI89thj9dalpqZaGvqvtHXrVoskyzPPPFNvXW1t7XVf72oVFRX1ln388ccWSZYdO3ZYl61atcoiyVJQUHDdbX/1q19ZPD09LZcuXbIuu++++yySLO+++65N24KCAoskS5cuXSznz5+3Lk9LS7NIsvTr189y5coV6/LHHnvM4ubmZrNvwFkZpf9JSEiwuLu7W7777jvrssOHD1tcXV3r9T2SLC4uLpZDhw7V28+P+4PLly9b+vTpYxk5cqTN8ttvv92SnJxsna/rW0aNGmXTd82cOdPi6upq0zeg+XCJx+BiYmK0d+9e6/0eX331lcaOHav+/fsrJydH0r8+1ZhMJg0dOrTF63n66acb3fZPf/qTTCaTXnrppXrr7Hk00MPDw/r3S5cu6Z///KcGDRokSdq7d2+jt71w4YL++c9/KiYmRhUVFTpy5IhNW7PZrF/84hcN7udnP/uZfH19rfN1p7MnTpyodu3a2Sy/fPmy/u///q+RRwcYlxH6n5qaGmVl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RgkJCfL09NTu3bv13nvv6Te/+U2DbX/zm99o9uzZ2rdvn+6880499thjqq6ubpbjaC1eeOEF/elPf9IHH3ygvXv3KjQ0VLGxsTp37py1zf/7f/9Pr776qvLz89W3b996+3jttde0Zs0arVq1Sjt37lRZWZm107+e119/XXfffbf++te/6te//rVSUlJ09OjR5jw83GL0G20HfUfzIqDYwdfXV97e3nJ1dVVAQECznS7dvHmzKioqFBsbK0maOHGiVq5c2ejtN23apBMnTujDDz9Uv379NHToUL3yyisNtp09e7bi4+N15513asGCBfruu+90/PjxZjmO1qC8vFwrVqzQ7373O8XFxSkiIkL/+Z//KQ8PD5v3ZOHChXrggQfUs2fPBk+3vv3220pLS9PDDz+ssLAw/f73v1fHjh1v+Ppjx47Vr3/9a4WGhmrOnDnq3Lmztm3b1pyHiFuMfqNtoO9ofgQUA3j//ff1yCOPqF27f90S9Nhjj2nnzp06ceJEo7Y/evSogoODFRAQYF127733Ntj26sQeGBgoSTpz5kxTS291Tpw4oStXrmjIkCHWZe3bt9e9996r/Px867K77777mvsoLS1VSUmJzXvg6uqqqKioG77+1e+PyWRSQEAA7w8aRL9hLPQdzY+AcpNcXFz0468zunLlSqO3P3funDZs2KB33nlH7dq1U7t27fSTn/xE1dXVev/995u7XJs7v00mkySptra22V+ntWupJyF+fGe+yWTi/WmF6DfaLvqOxiOg3KQuXbqoqKjIOl9WVqaCgoJGb79mzRp169ZN3377rfbt22edXn/9da1evVo1NTU33Efv3r116tQplZSUWJc113XutqZnz55yc3PTzp07rcuuXLmib775RhEREY3ah6+vr/z9/W3eg5qaGu3du7fZ64Vzot9ofeg7mh+PGd+kkSNHavXq1Ro3bpw6duyoefPmydXVtdHbr1y5UhMmTFCfPn1slgcHBystLU0bN25UfHz8dfdRdz0zOTlZS5Ys0YULFzR37lxJP3zaQeN06NBBKSkpev755+Xn56fu3btryZIlqqio0JQpU/Ttt982aj8zZsxQenq6QkNDFRYWprffflvff/897wck0W+0RvQdzY8zKDcpLS1N9913nx588EHFx8crISFBPXv2bNS2eXl5+vbbb5WUlFRvna+vr+6///5G3fTm6uqqjIwMXbx4Uffcc4+eeuop69347u7u9h0Q9OqrryopKUmTJk3SgAEDdPz4cWVlZem2225r9D7mzJmjxx57TE8++aSio6Pl5eWl2NhY3g9Iot9oreg7mpfJ8uMLoWgVdu7cqaFDh+r48eON7vjQcmpraxUeHq6f//znWrRokaPLARpEv2E8bbnv4BJPK7FhwwZ5eXmpV69eOn78uP7t3/5NQ4YMoZNxkO+++05ffvml7rvvPlVVVen3v/+9CgoK9Pjjjzu6NMCKfsN46Dt+QEBpJS5cuKA5c+bo5MmT6ty5s0aNGqXXX3/d0WW1WS4uLlq9erVmz54ti8WiPn36aPPmzQoPD3d0aYAV/Ybx0Hf8gEs8AADAcLhJFgAAGA4BBQAAGA4BBQAAGA4BBQAAGA4BBQAAGA4BBQAAGA4BBQAAGA4BBQAAGM7/B7IeMbhbIoouAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 800x200 with 0 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "attri = [\"rtc_alarm\",\"drain\"]\n",
    "\n",
    "# 创建一个2行2列的子图\n",
    "fig, axs = plt.subplots(1,2)\n",
    "\n",
    "for i in range(len(attri)):\n",
    "    for j in range(len(networks)):\n",
    "        axs[i].boxplot([network_data.get(networks[j]).get(strategies_list[0]).get(attri[i]),\n",
    "                     network_data.get(networks[j]).get(strategies_list[1]).get(attri[i])],showmeans=True,meanline=True)\n",
    "        axs[i].set_xticklabels([strategies_list[0], strategies_list[1]])\n",
    "        axs[i].set_title(networks[j]+\" \"+attri[i])\n",
    "\n",
    "# 调整子图之间的垂直间距\n",
    "plt.subplots_adjust(hspace=0.5)\n",
    "plt.figure(figsize=(8,2))\n",
    "# 显示图形\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "57ef00b0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "wifi\n",
      "Align\n",
      "平均值: 20.71641440061965\n",
      "标准差: 1.8824587599441795\n",
      "中位数: 20.231054357754488\n",
      "Origin\n",
      "平均值: 21.545871756977686\n",
      "标准差: 2.099376071387203\n",
      "中位数: 21.07594892484147\n",
      "\n",
      "下降比例: -3.8497275288451136%\n",
      "下降比例: -10.332465650124863%\n",
      "下降比例: -4.008809141168181%\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "def calculate_stats(arr):\n",
    "    mean = np.mean(arr)\n",
    "    std = np.std(arr)\n",
    "    median = np.median(arr)\n",
    "    return mean, std, median\n",
    "\n",
    "# 使用箱型图的方法去除异常值\n",
    "def remove_outliers(data):\n",
    "    q1 = np.percentile(data, 25)\n",
    "    q3 = np.percentile(data, 75)\n",
    "    iqr = q3 - q1\n",
    "    lower_bound = q1 - 1.5 * iqr\n",
    "    upper_bound = q3 + 1.5 * iqr\n",
    "    filtered_data = [x for x in data if lower_bound <= x <= upper_bound]\n",
    "    return filtered_data\n",
    "\n",
    "arr = [1, 2, 3, 4, 5]\n",
    "\n",
    "\n",
    "for j in range(len(networks)):\n",
    "    align_drain = network_data.get(networks[j]).get(strategies_list[0]).get(attri[1])\n",
    "    origin_drain = network_data.get(networks[j]).get(strategies_list[1]).get(attri[1])\n",
    "    align_drain = remove_outliers(align_drain)\n",
    "    origin_drain = remove_outliers(origin_drain)\n",
    "    mean, std, median = calculate_stats(align_drain)\n",
    "    print(\"\\n\"+networks[j])\n",
    "    print(\"Align\")\n",
    "    print(f'平均值: {mean}')\n",
    "    print(f'标准差: {std}')\n",
    "    print(f'中位数: {median}')\n",
    "    origin_mean, origin_std, origin_median = calculate_stats(origin_drain)\n",
    "    print(\"Origin\")\n",
    "    m = -(origin_mean - mean)/origin_mean * 100\n",
    "    n = -(origin_std -std)/origin_std * 100\n",
    "    q = -(origin_median -median)/origin_median * 100\n",
    "    print(f'平均值: {origin_mean}')\n",
    "    print(f'标准差: {origin_std}')\n",
    "    print(f'中位数: {origin_median}')\n",
    "    \n",
    "    print(f'\\n下降比例: {m}%')\n",
    "    print(f'下降比例: {n}%')\n",
    "    print(f'下降比例: {q}%')\n",
    "    \n",
    "    \n",
    "                                                                             "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "bea40d69",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "wifi\n",
      "Align\n",
      "平均值: 194.5\n",
      "标准差: 90.14016862642315\n",
      "中位数: 214.5\n",
      "Origin\n",
      "平均值: 207.375\n",
      "标准差: 84.42146868540016\n",
      "中位数: 224.5\n",
      "\n",
      "下降比例: -6.208559373116335%\n",
      "下降比例: 6.773987742778967%\n",
      "下降比例: -4.4543429844097995%\n"
     ]
    }
   ],
   "source": [
    "for j in range(len(networks)):\n",
    "    align_alarm = network_data.get(networks[j]).get(strategies_list[0]).get(attri[0])\n",
    "    origin_alarm = network_data.get(networks[j]).get(strategies_list[1]).get(attri[0])\n",
    "    align_alarm = remove_outliers(align_alarm)\n",
    "    origin_alarm = remove_outliers(origin_alarm)\n",
    "    mean, std, median = calculate_stats(align_alarm)\n",
    "    print(\"\\n\"+networks[j])\n",
    "    print(\"Align\")\n",
    "    print(f'平均值: {mean}')\n",
    "    print(f'标准差: {std}')\n",
    "    print(f'中位数: {median}')\n",
    "    origin_mean, origin_std, origin_median = calculate_stats(origin_alarm)\n",
    "    print(\"Origin\")\n",
    "    m = -(origin_mean - mean)/origin_mean * 100\n",
    "    n = -(origin_std -std)/origin_std * 100\n",
    "    q = -(origin_median -median)/origin_median * 100\n",
    "    print(f'平均值: {origin_mean}')\n",
    "    print(f'标准差: {origin_std}')\n",
    "    print(f'中位数: {origin_median}')\n",
    "    \n",
    "    print(f'\\n下降比例: {m}%')\n",
    "    print(f'下降比例: {n}%')\n",
    "    print(f'下降比例: {q}%')\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "75e2b8e0",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
